from django.shortcuts import render
from rest_framework.generics import CreateAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from django_redis import get_redis_connection
import pickle, base64

# Create your views here.
from carts.serializers import CartsSerializer, CartsSKUSerializer, CartsDeleteSerializer, CartsSelectionSerializer
from goods.models import SKU


class CartsView(APIView):
    """
        增加购物车数据
    """

    def perform_authentication(self, request):
        # 调用视图方法前先调用验证方法，原生方法不满足验证需求，重写后pass不执行
        pass

    def get(self, request):

        # 登录状态判断
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 已登录用户
            # 1、建立redis连接
            conn = get_redis_connection('cart')
            # 2、获取商品id和数量。hash
            sku_count = conn.hgetall('cart_%s' % user.id)  # {bsku_id:count)
            # 3、获取选中状态sets
            sku_selected = conn.smembers('cart_selectes_%s' % user.id)  # {sku_id1,sku_id2}
            # 4、构建字典
            cart = {}
            for sku_id, count in sku_count.items():
                cart[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in sku_selected
                }
        else:
            # 未登录用户
            # 1、先获取cookie，判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            # 2、有cookie值，解密cookie，在原来值的基础上写入
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                cart = {}

        # 根据sku_id查询商品
        skus = SKU.objects.filter(id__in=cart.keys())
        for sku in skus:
            sku.count = cart[sku.id]['count']
            sku.selected = cart[sku.id]['selected']
        # 序列化返回商品
        ser = CartsSKUSerializer(skus, many=True)

        return Response(ser.data)

    def post(self, request):
        # 1、获取前端数据
        data = request.data
        # 2、校验数据
        ser = CartsSerializer(data=data)
        ser.is_valid(raise_exception=True)

        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']
        # 3、保存数据
        # 登录状态判断
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 已登录用户
            # 1、建立redis连接
            conn = get_redis_connection('cart')
            # 2、写入商品id和数量。hash
            conn.hincrby('cart_%s' % user.id, sku_id, count)
            # 3、写入选中状态sets
            if selected:
                conn.sadd('cart_selectes_%s' % user.id, sku_id)
            # 4、结果返回
            return Response('ok')
        else:
            # 未登录用户
            # 1、先获取cookie，判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            # 2、有cookie值，解密cookie，在原来值的基础上写入
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                cart = {}

            sku_dict = cart.get(sku_id)  # {14:{'count:1}}
            # 累加
            if sku_dict:
                count += int(sku_dict['count'])

            # 3、写入数据
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 4、将cart字典数据转化为字符串
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            # 5、将转化后的字符串数据写入cookie
            respone = Response('ok')
            respone.set_cookie('cart_cookie', cart_cookie, 60 * 60 * 24 * 7)
            # 6、返回结果
            return respone

    def put(self, request):
        # 1、获取前端数据
        data = request.data
        # 2、校验数据
        ser = CartsSerializer(data=data)
        ser.is_valid(raise_exception=True)

        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']
        # 3、保存数据
        # 登录状态判断
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 已登录用户
            # 1、建立redis连接
            conn = get_redis_connection('cart')
            # 2、更新商品id和数量。hash
            conn.hset('cart_%s' % user.id, sku_id, count)
            # 3、更新选中状态sets
            if selected:
                conn.sadd('cart_selectes_%s' % user.id, sku_id)
            else:
                conn.srem('cart_selectes_%s' % user.id, sku_id)
            # 4、结果返回
            return Response(ser.data)
        else:
            # 未登录用户
            # 1、先获取cookie，判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            # 2、有cookie值，解密cookie，在原来值的基础上写入
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                cart = {}

            # 3、写入数据
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 4、将cart字典数据转化为字符串
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            # 5、将转化后的字符串数据写入cookie
            respone = Response(ser.data)
            respone.set_cookie('cart_cookie', cart_cookie, 60 * 60 * 24 * 7)
            # 6、返回结果
            return respone

    def delete(self, request):
        # 1、获取前端数据
        data = request.data
        # 2、校验数据
        ser = CartsDeleteSerializer(data=data)
        ser.is_valid(raise_exception=True)

        sku_id = ser.validated_data['sku_id']

        # 3、保存数据
        # 登录状态判断
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 已登录用户
            # 1、建立redis连接
            conn = get_redis_connection('cart')
            # 2、删除商品id和数量。hash
            conn.hdel('cart_%s' % user.id, sku_id)
            # 3、删除选中状态sets
            conn.srem('cart_selectes_%s' % user.id, sku_id)
            # 4、结果返回
            return Response('ok')
        else:
            # 未登录用户
            # 1、先获取cookie，判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            # 2、有cookie值，解密cookie，在原来值的基础上写入
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
                # 3、删除数据
                if sku_id in cart.keys():
                    del cart[sku_id]
                # 4、将cart字典数据转化为字符串
                cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()

            # 5、将转化后的字符串数据写入cookie
            respone = Response('ok')
            respone.set_cookie('cart_cookie', cart_cookie, 60 * 60 * 24 * 7)
            # 6、返回结果
            return respone


class CartSelectionView(APIView):
    def perform_authentication(self, request):
        # 调用视图方法前先调用验证方法，原生方法不满足验证需求，重写后pass不执行
        pass

    def put(self, request):
        # 1、获取前端数据
        data = request.data
        # 2、校验数据
        ser = CartsSelectionSerializer(data=data)
        ser.is_valid(raise_exception=True)

        selected = ser.validated_data['selected']
        # 3、保存数据
        # 登录状态判断
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 已登录用户
            # 1、建立redis连接
            conn = get_redis_connection('cart')
            # 2、获取商品id和数量。hash
            sku_count = conn.hgetall('cart_%s' % user.id)
            sku_ids = sku_count.keys()  # [1,2,3,5]
            # 3、更新选中状态sets
            if selected:
                conn.sadd('cart_selectes_%s' % user.id, *sku_ids)
            else:
                conn.srem('cart_selectes_%s' % user.id, *sku_ids)
            # 4、结果返回
            return Response(ser.data)
        else:
            # 未登录用户
            # 1、先获取cookie，判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            # 2、有cookie值，解密cookie，在原来值的基础上写入
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                cart = {}

            # 3、更新数据
            for sku_id, data_dict in cart.items():
                cart[sku_id]['selected'] = selected

            # 4、将cart字典数据转化为字符串
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            # 5、将转化后的字符串数据写入cookie
            respone = Response(ser.data)
            respone.set_cookie('cart_cookie', cart_cookie, 60 * 60 * 24 * 7)
            # 6、返回结果
            return respone
